#include "game_field.h"

#include <game_model.h>
#include <qpopupmenu.h>
#include <qcursor.h> 

#include <qpainter.h>
#include <queue>
#include <stdio.h>
#include <memory.h>

//#
GameField::GameField (GameController * _gc, QWidget* parent, const char* name, WFlags fl)
:QWidget (parent, name, fl), gameController (_gc)
{
	setMouseTracking( TRUE ); 
	
}

//#
GameField::~GameField () {
}

//#
void GameField::init () {
	GameController * _gc = gameController;
	menu = new QPopupMenu (this);
	TRACE ("GF 1");
	gMenu = new QPopupMenu (this);
	TRACE ("GF 2, _gc = %p", _gc);
	_gc->gw->gameNewAction->addTo (gMenu);
	TRACE ("GF..");
	_gc->gw->gameEndForAllAction->addTo (gMenu);
	_gc->gw->gameResetAction->addTo (gMenu);
	_gc->gw->gameMenu->insertSeparator ();
	_gc->gw->gameSettingsAction->addTo (gMenu);
	_gc->gw->gameGlobalSettings->addTo (gMenu);
	gMenu->insertSeparator ();
	_gc->gw->gameExitAction->addTo (gMenu);
	iMenu = new QPopupMenu( this );
	_gc->gw->infoRatingAction->addTo (iMenu);
	hMenu = new QPopupMenu (this );
	_gc->gw->helpContentsAction->addTo( hMenu );
	_gc->gw->helpRulesAction->addTo (hMenu);
    _gc->gw->helpMenu->insertSeparator();
    _gc->gw->helpAboutAction->addTo( hMenu );

	menu->insertItem ("Game", gMenu);
	menu->insertItem ("Info", iMenu);
	menu->insertItem ("Help", hMenu);
}

//#
void GameField::setGameController (GameController * _g) {
	gameController = _g;
}

GameController * GameField::getGameController () {
	return gameController;
}

//#
QSizePolicy GameField::sizePolicy() const {
	return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
}

//#
QSize GameField::sizeHint () const {
	return QSize ((rows ()-1)*cellSize() + 2*border(), (cols()-1)*cellSize() + 2*border());
}

//#
int GameField::rows () const {
	if (gameController->getCurrentGame ())
		return gameController->getCurrentGame ()->getModel()->getHeight ();
	else
		return gameController->getFieldHeight ();
}

//#
int GameField::cellSize () const {
	return 20;
}

//#
int GameField::cols () const {
	if (gameController->getCurrentGame ())
		return gameController->getCurrentGame ()->getModel()->getWidth ();
	else
		return gameController->getFieldWidth ();
}

int GameField::border () const {
	return 20;
}

//#
void GameField::paintEvent( QPaintEvent * e) {
	QWidget::paintEvent (e);
	QPainter p (this);
	p.fillRect (rect (), QBrush(QColor("white")));
	//draw grid
	int i, j;
	int x = border(), y = border();
	for (i = 0; i < rows (); i++, x += cellSize ())
		for (j = 0; j < cols (); j++, y += cellSize ()) {
			p.drawLine (border(), y, width ()- border(), y);
			p.drawLine (x, border(), x, height ()- border());
		}
	// draw all positions
	Game * cGame;
	if (NULL == (cGame = this->gameController->getCurrentGame())) 
		return;
	DotsGameModel * gm = cGame->getModel ();
	PlayerProfile * profile;
	DotsGameCell * cell;
	//int x, y;
	for (i = 0; i < rows (); i++) {
		for (j = 0; j < cols (); j++) {
			cell = gm->getCell (i, j);
			if (!cell->free) {
				profile = cell->player;
				x = i*cellSize() + border ();
				y = j*cellSize() + border ();
				p.setBrush (QColor(QRgb(profile->color)));
				p.drawEllipse (x - 5, y - 5, 10, 10);
			}
		}
	}
	// draw filled region
}

//#
void GameField::mousePressEvent ( QMouseEvent * e )  {
	QWidget ::mousePressEvent (e);
	if (e->button() == QMouseEvent::LeftButton) {
		if (curI == -1 || curJ == -1)
			return;
		gameController->moveEvent(new GameMoveEvent(Point (curJ, curI)));
		repaint (e->x() - 5, e->y() - 5, 10, 10);
	} 
}

//#
void GameField::contextMenuEvent ( QContextMenuEvent * e ) {
	TRACE ("popuping");
	menu->exec (QCursor::pos());
}

//#
void GameField::leaveEvent ( QEvent * ) {
	//repaint();
}

//#
void GameField::mouseReleaseEvent ( QMouseEvent * e ) {
	QWidget::mouseReleaseEvent(e);
}

//#
void GameField::mouseMoveEvent ( QMouseEvent * e )  {
	Game * cGame;
	if (NULL == (cGame = this->gameController->getCurrentGame())) 
		return;
	PlayerProfile * profile;
	profile = cGame->getPlayer (cGame->getCurrentPlayer());
	static std::queue<QPoint> toClear;
	QWidget::mouseMoveEvent(e);
	int X = e->x() - border();
	int Y = e->y() - border();

	bool outside = false;

	if (X < 0 || X > (cols()-1)*cellSize())
		outside = true;
	if (Y < 0 || Y > (rows()-1)*cellSize())
		outside = true;

	int dx = X % cellSize ();
	if (dx > cellSize ()/2)
		dx = cellSize () - dx;
	int dy = Y % cellSize ();
	if (dy > cellSize ()/2)
		dy = cellSize () - dy;
	
	if (dx <= 5 && dy <= 5 && !outside) {
		QPainter p (this);
		//calc x
		int newX = X / cellSize ();		
		curJ = newX;
		newX *= cellSize();
		if (X - newX > cellSize()/2) {
			newX += cellSize ();
			curJ++;
		}
		//calc y
		int newY = Y / cellSize ();
		curI = newY;
		newY *= cellSize();
		if (Y - newY > cellSize()/2) {
			newY += cellSize ();
			curI++;
		}
		//draw
		newX += border ();
		newY += border ();
		p.setBrush (QColor(QRgb(profile->color)));
		p.drawEllipse (QRect(newX - 4, newY - 4, 8, 8));
		toClear.push (QPoint (newX, newY));

	} else {
		curI = curJ = -1;
		while (!toClear.empty()) {
			QPoint pt = toClear.front ();
			toClear.pop ();
			int x = pt.x();
			int y = pt.y();
			this->repaint (QRect (x - 4, y - 4, 8 , 8));
		}
	}
}

//#
void GameField::resizeEvent ( QResizeEvent * ) {
	repaint();
}
